/* 
 如何创建一个函数组件
   + 创建一个函数
   + 函数返回的是一个“JSX元素(VirtualDOM)”

 props接收传递进来的属性（含子节点）
   + 被冻结的「只读的」，如果需要修改，我们可以把属性值赋值给其他的变量/状态，以后基于修改变量/状态来改值
   + 虽然不能直接修改props，但是我们可以对props进行规则校验
     设置默认值：组件.defaultProps = { ... }
     属性规则设置：
       依赖官方插件 prop-types 「$ yarn add prop-types」
       https://github.com/facebook/prop-types
       组件.propTypes = {
         ...
       }
       备注：props中的信息是在创建VirtualDOM的时候就获取到了，而规则校验是在函数执行的时候，把传递进来的props中的每一项，按照规则进行校验的，所以即便不符合校验规则，也仅仅是在控制台输出Warning警告错误，但是不影响props中的值！

 在Vue框架中，我们可以基于 <slot> 和 v-slot(简写#) 来处理插槽信息（而且有具名插槽和作用域插槽）；React默认是不具备插槽这个概念的，但是真实项目中，插槽还是有用的！
   插槽作用：把外界的一些视图，基于插槽传递到组件内部渲染，以此来增强组件的复用性！
   具体处理办法：基于 props.children（存储了调用插槽时设置的子节点）
     + 如果组件只预留一个插槽，则直接在插槽位置，渲染 props.children 即可！
     + 但是如果预留了很多插槽，则需要给插槽设置名字，后续调用的时候，指定名字，让其渲染到组件内部的特定位置
   我们可以把传递的 children 做特殊的处理
   我们可以基于 React.Children 中提供的方法来处理插槽信息
 */
import React from 'react'
import PT from 'prop-types'

const DemoOne = function DemoOne(props) {
    let x = props.x,
        children = React.Children.toArray(props.children),
        header = [],
        footer = []
    // x = 1000
    children.forEach(item => {
        if (item.props.name === 'slot1') {
            header.push(item)
        }
        if (item.props.name === 'slot2') {
            footer.push(item)
        }
    })

    return <div className="demo-box"
        onClick={() => {
            x = 2000
            console.log(x)
        }}>
        {header}
        <br />
        纯函数组件 {props.title} && {x}
        <br />
        {footer}
    </div>
}
// 设置传递属性的默认值
DemoOne.defaultProps = {
    x: 0,
    y: false
}
// 设置其它的规则「必传、类型...」
DemoOne.propTypes = {
    title: PT.string.isRequired, //字符串类型 & 必须传
    x: PT.oneOfType([  //多类型
        PT.number,
        PT.string
    ]),
    // y: PT.bool,
    customProp(props) { //自定义校验规则
        if (typeof props.y !== 'boolean') {
            return new Error(`y is not a boolean`)
        }
    }
}
export default DemoOne